package com.huimingpay.merchant.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huimingpay.common.domain.BusinessException;
import com.huimingpay.common.domain.CommonErrorCode;
import com.huimingpay.common.util.PhoneUtil;
import com.huimingpay.common.util.StringUtil;
import com.huimingpay.merchant.api.MerchantService;
import com.huimingpay.merchant.convert.MerchantConvert;
import com.huimingpay.merchant.convert.StaffConvert;
import com.huimingpay.merchant.convert.StoreConvert;
import com.huimingpay.merchant.dto.MerchantDTO;
import com.huimingpay.merchant.dto.StaffDTO;
import com.huimingpay.merchant.dto.StoreDTO;
import com.huimingpay.merchant.entity.Merchant;
import com.huimingpay.merchant.entity.Staff;
import com.huimingpay.merchant.entity.Store;
import com.huimingpay.merchant.entity.StoreStaff;
import com.huimingpay.merchant.mapper.MerchantMapper;
import com.huimingpay.merchant.mapper.StaffMapper;
import com.huimingpay.merchant.mapper.StoreMapper;
import com.huimingpay.merchant.mapper.StoreStaffMapper;
import com.huimingpay.user.api.TenantService;
import com.huimingpay.user.dto.tenant.CreateTenantRequestDTO;
import com.huimingpay.user.dto.tenant.TenantDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;

import javax.annotation.Resource;

/**
 * ClassName:MerchantServiceImpl
 * Package:com.huimingpay.merchant.service
 * Time: 2024/7/17
 */
@Slf4j
@Service
public class MerchantServiceImpl implements MerchantService {
    @Resource
    MerchantMapper merchantMapper;

    @Resource
    StoreMapper storeMapper;

    @Resource
    StaffMapper staffMapper;

    @Resource
    StoreStaffMapper storeStaffMapper;

    @Reference // 注入远程服务
    TenantService tenantService;


    /**
     * 根据商家ID查询商家信息
     *
     * @param merchantId 商家ID
     * @return MerchantDTO 商家信息的DTO对象
     */
    @Override
    public MerchantDTO queryMerchantById(Long merchantId) {
        // 通过商家ID从数据库中查询商家信息
        Merchant merchant = merchantMapper.selectById(merchantId);

        // 判断商家信息是否存在
        if (merchant != null) {
            MerchantDTO merchantDTO = MerchantConvert.INSTANCE.EntityToDTO(merchant);
            return merchantDTO;
        }
        return null;
    }

    /**
     * 商户注册
     *
     * @param merchantDTO 商户信息
     * @return
     */
    @Override
    //@Transactional
    public MerchantDTO createMerchant(MerchantDTO merchantDTO) throws BusinessException {
        //1、合法性校验
        // 判断商户信息是否存在
        if (merchantDTO == null) {
            throw new BusinessException(CommonErrorCode.E_100108); //E_100108 传入对象为空
        }
        // 判断手机号是否为空
        if (StringUtil.isEmpty(merchantDTO.getMobile())) {
            throw new BusinessException(CommonErrorCode.E_100112); //E_100112 手机号为空
        }
        // 判断手机号格式是否正确
        if (!PhoneUtil.isMatches(merchantDTO.getMobile())) {
            throw new BusinessException(CommonErrorCode.E_100109); //E_100109 手机号格式错误
        }
        // 判断用户名是否为空
        if (StringUtil.isEmpty(merchantDTO.getUsername())) {
            throw new BusinessException(CommonErrorCode.E_100110); //E_100110 用户名为空
        }
        // 判断密码是否为空
        if (StringUtil.isEmpty(merchantDTO.getPassword())) {
            throw new BusinessException(CommonErrorCode.E_100111); //E_100111 密码为空
        }

        // 判断手机号是否已存在
        LambdaQueryWrapper<Merchant> queryWrapper = new LambdaQueryWrapper<>();

        // 等价于WHERE mobile = merchantDTO.getMobile()
        queryWrapper.eq(Merchant::getMobile, merchantDTO.getMobile());

        Integer selectCount = merchantMapper.selectCount(queryWrapper);
        if (selectCount > 0) {
            throw new BusinessException(CommonErrorCode.E_100113); //E_100113 手机号已存在
        }


        //2、调用Saas接口 添加 租户并绑定和门店 员工 商户之间的关联关系
        /**
         * 相关参数
         * 1、手机号
         * 2、账号
         * 3、密码
         * 4、租户类型：huiming-merchant
         *5、默认套餐：huiming-merchant
         *6、租户名称，同账号名
         */
        CreateTenantRequestDTO createTenantRequestDTO = new CreateTenantRequestDTO();
        createTenantRequestDTO.setMobile(merchantDTO.getMobile());
        //租户的账号信息
        createTenantRequestDTO.setUsername(merchantDTO.getUsername());
        createTenantRequestDTO.setPassword(merchantDTO.getPassword());
        //表示该租户类型是huiming-merchant
        createTenantRequestDTO.setTenantTypeCode("huiming-merchant");
        //设置商户的租户套餐为初始化套餐（根据套餐分配权限）
        createTenantRequestDTO.setBundleCode("huiming-merchant");
        //设置租户名称,租户名称和账号名一致
        createTenantRequestDTO.setName(merchantDTO.getUsername());

        //创建租户账号，如果该租户在Saas已存在，则直接返回该租户对象
        TenantDTO tenantAndAccount = tenantService.createTenantAndAccount(createTenantRequestDTO);
        //获取该租户的id
        //校验租户id是否为空
        if (tenantAndAccount == null || tenantAndAccount.getId() == null) {
            throw new BusinessException(CommonErrorCode.E_200012); //E_200012 租户不存在
        }
        //租户id
        Long tenantAndAccountId = tenantAndAccount.getId();
        //租户id在商户表是唯一的，意味着租户和商户是一一对应的
        //因此在商户表根据租户id查询记录，如果存在，则表示该商户已在当前租户下注册，不可重复注册
        Integer count = merchantMapper.selectCount(new LambdaQueryWrapper<Merchant>().eq(Merchant::getTenantId, tenantAndAccountId));
        if (count>0) {
            throw new BusinessException(CommonErrorCode.E_200017);
        }

        // 3、设置租户和商户的绑定关系，即在商户中添加租户的id
        Merchant merchantEntity = MerchantConvert.INSTANCE.DTOToEntity(merchantDTO);
        // 设置对应的租户id
        merchantEntity.setTenantId(tenantAndAccountId); //商户和租户是一一对应的
        //设置审核状态 0-未申请 1-已申请待审核 2-审核通过 3-审核失败
        merchantEntity.setAuditStatus("0");
        //保存商户信息
        merchantMapper.insert(merchantEntity);

        //4、新增门店  创建根门店
        StoreDTO storeDTO = new StoreDTO();
        storeDTO.setStoreName("根门店");
        storeDTO.setMerchantId(merchantEntity.getId());
        StoreDTO store = createStore(storeDTO);

        //5、新增员工
        StaffDTO staffDTO = new StaffDTO();
        staffDTO.setUsername(merchantDTO.getUsername()); //用户名 账号
        staffDTO.setMobile(merchantDTO.getMobile()); //手机号
        //给员工设置所属门店，此处为根门店
        staffDTO.setStoreId(store.getId()); //员工所属门店id
        staffDTO.setMerchantId(merchantEntity.getId()); //所属商户id
        StaffDTO staff = createStaff(staffDTO);

        //6、绑定该员工到门店 即将相应的员工id和门店id添加到门店员工表
        //由于绑定的是根门店，即为门店设置管理员
        bindStaffToStore(store.getId(), staff.getId());

        //7、返回商户信息
        MerchantDTO merchantDTO1 = MerchantConvert.INSTANCE.EntityToDTO(merchantEntity);
        return merchantDTO1;
    }

    @Override
    public void applyMerchant(Long merchantId, MerchantDTO merchantDTO) throws BusinessException {
        // 校验merchantDTO、merchantId是否存在
        if (merchantId == null || merchantDTO == null) {
            throw new BusinessException(CommonErrorCode.E_300009); //E_300009 传入对象为空或者缺少必要的参数
        }
        //校验merchantId合法性，查询商户表，如果查询不到记录，认为非法
        Merchant merchant = merchantMapper.selectById(merchantId);
        if (merchant == null) {
            throw new BusinessException(CommonErrorCode.E_200002); //E_200002 商户不存在
        }

        //DTO转成Entity
        Merchant entity = MerchantConvert.INSTANCE.DTOToEntity(merchantDTO);
        //将必要的参数从merchant传到entity
        entity.setId(merchant.getId());
        entity.setMobile(merchant.getMobile());//因为资质申请的时候手机号不让改，还使用数据库中原来的手机号
        entity.setAuditStatus("1");//审核状态1-已申请待审核
        entity.setTenantId(merchant.getTenantId());
        //调用mapper更新商户表
        merchantMapper.updateById(entity);
    }

    /**
     * 商户下新增门店
     *
     * @param storeDTO 门店信息
     * @return 门店信息
     * @throws BusinessException
     */
    @Override
    public StoreDTO createStore(StoreDTO storeDTO) throws BusinessException {
        Store store = StoreConvert.INSTANCE.DTOToEntity(storeDTO);
        log.info("商户下新增门店：" + JSON.toJSONString(store));
        storeMapper.insert(store);
        return StoreConvert.INSTANCE.EntityToDTO(store);
    }

    /**
     * 商户下新增员工
     *
     * @param staffDTO 员工信息
     * @return 员工信息
     * @throws BusinessException
     */
    @Override
    public StaffDTO createStaff(StaffDTO staffDTO) throws BusinessException {
        //1、合法性校验
        //校验手机号是否存在及格式是否正确
        String mobile = staffDTO.getMobile();
        if (StringUtil.isBlank(mobile)) {
            throw new BusinessException(CommonErrorCode.E_100112); //E_100112 手机号为空
        }
        if (!PhoneUtil.isMatches(mobile)) {
            throw new BusinessException(CommonErrorCode.E_100109); //E_100109 手机号格式错误
        }
        //根据商户id和手机号校验手机号是否已存在
        if (isExitsStaffByMobile(mobile, staffDTO.getMerchantId())) {
            throw new BusinessException(CommonErrorCode.E_100113); //E_100113 手机号已存在
        }

        //校验用户名是否为空
        String username = staffDTO.getUsername();
        if (StringUtil.isBlank(username)) {
            throw new BusinessException(CommonErrorCode.E_100110); //E_100110 用户名为空
        }
        //根据商户id和用户名校验用户名是否已存在
        if (isExitsStaffByUsername(username, staffDTO.getMerchantId())) {
            throw new BusinessException(CommonErrorCode.E_100114); //E_100114 用户名已存在
        }

        //2、保存员工信息
        Staff staff = StaffConvert.INSTANCE.DTOToEntity(staffDTO);
        log.info("商户下新增员工：" + JSON.toJSONString(staff));
        staffMapper.insert(staff);
        //3、返回员工信息
        return StaffConvert.INSTANCE.EntityToDTO(staff);
    }

    /**
     * 绑定员工到门店
     *
     * @param staffId 员工ID
     * @param storeId 门店ID
     * @throws BusinessException
     */
    @Override
    public void bindStaffToStore(Long staffId, Long storeId) throws BusinessException {
        StoreStaff storeStaff = new StoreStaff();
        storeStaff.setStoreId(storeId);
        storeStaff.setStaffId(staffId);
        storeStaffMapper.insert(storeStaff);
    }

    /**
     * 根据商户id和手机号校验手机号是否已存在
     *
     * @param mobile     手机号
     * @param merchantId 商户id
     * @return 手机号是否存在  true-存在，false-不存在
     */
    private Boolean isExitsStaffByMobile(String mobile, Long merchantId) {
        // 创建一个LambdaQueryWrapper对象用于构建查询条件
        LambdaQueryWrapper<Staff> queryWrapper = new LambdaQueryWrapper<>();
        // 添加查询条件：手机号等于传入的手机号，并且商户id等于传入的商户id
        queryWrapper.eq(Staff::getMobile, mobile)
                .eq(Staff::getMerchantId, merchantId);
        // 执行查询，返回满足条件的记录数
        Integer integer = staffMapper.selectCount(queryWrapper);
        // 判断记录数是否大于0，若大于0则表示手机号已存在，返回true；否则返回false
        return integer > 0;
    }


    /**
     * 根据商户id和用户名校验用户名是否已存在
     *
     * @param username   用户名
     * @param merchantId 商户id
     * @return 用户名是否存在  true-存在，false-不存在
     */
    public Boolean isExitsStaffByUsername(String username, Long merchantId) {
        // 创建一个LambdaQueryWrapper对象用于构建查询条件
        LambdaQueryWrapper<Staff> queryWrapper = new LambdaQueryWrapper<>();
        // 添加查询条件：用户名等于传入的用户名，并且商户id等于传入的商户id
        queryWrapper.eq(Staff::getUsername, username)
                .eq(Staff::getMerchantId, merchantId);
        // 执行查询，返回满足条件的记录数
        Integer integer = staffMapper.selectCount(queryWrapper);
        // 判断记录数是否大于0，若大于0则表示用户名已存在，返回true；否则返回false
        return integer > 0;
    }


}
